"""现代分页实现示例

展示使用现成分页库的几种方法。
"""

from typing import List
import logging
from fastapi_pagination import Page, paginate
from fastapi_pagination.params import Params
from sqlmodel import select

from model.his.yp1 import Yp1
from core.db_manager import get_db_session
from config.config_manager import get_hospital_config

logger = logging.getLogger(__name__)


# 方法1: 使用 fastapi-pagination 库（推荐）
def get_drug_dict_with_fastapi_pagination(
    page: int = 1, 
    size: int = 1000
) -> Page[Yp1]:
    """使用 fastapi-pagination 库实现分页
    
    Args:
        page: 页码，从1开始
        size: 每页条数
        
    Returns:
        Page[Yp1]: 包含分页信息的结果
    """
    hospital_config = get_hospital_config()
    hospital_name = hospital_config.get("name", "医院")
    
    try:
        logger.info(f"使用 fastapi-pagination 查询 {hospital_name} 药品字典 (第 {page} 页，每页 {size} 条)")
        
        with get_db_session() as session:
            statement = select(Yp1)
            # 使用 fastapi-pagination 的 paginate 函数
            result = paginate(session, statement, params=Params(page=page, size=size))
        
        logger.info(f"成功获取 {len(result.items)} 条药品数据")
        return result
        
    except Exception as e:
        logger.error(f"分页查询 {hospital_name} 药品字典失败: {e}", exc_info=True)
        # 返回空的分页结果
        return Page(items=[], total=0, page=page, size=size, pages=0)


# 方法2: 使用 SQLAlchemy 的内置分页（如果使用 SQLAlchemy 2.0+）
def get_drug_dict_with_sqlalchemy_pagination(
    page: int = 1,
    page_size: int = 1000
) -> dict:
    """使用 SQLAlchemy 2.0+ 的内置分页功能
    
    Args:
        page: 页码，从1开始
        page_size: 每页条数
        
    Returns:
        dict: 包含数据和分页信息的字典
    """
    hospital_config = get_hospital_config()
    hospital_name = hospital_config.get("name", "医院")
    
    try:
        logger.info(f"使用 SQLAlchemy 分页查询 {hospital_name} 药品字典 (第 {page} 页，每页 {page_size} 条)")
        
        with get_db_session() as session:
            # 使用 SQLAlchemy 2.0+ 的内置分页
            from sqlalchemy import func
            
            # 获取总数
            count_stmt = select(func.count(Yp1.idm))
            total = session.execute(count_stmt).scalar()
            
            # 分页查询
            offset = (page - 1) * page_size
            statement = select(Yp1).offset(offset).limit(page_size)
            results = session.execute(statement).scalars().all()
            
            # 计算分页信息
            total_pages = (total + page_size - 1) // page_size if total > 0 else 0
            has_next = page < total_pages
            has_prev = page > 1
            
            return {
                "data": results,
                "pagination": {
                    "current_page": page,
                    "page_size": page_size,
                    "total_count": total,
                    "total_pages": total_pages,
                    "has_next": has_next,
                    "has_prev": has_prev
                }
            }
            
    except Exception as e:
        logger.error(f"SQLAlchemy 分页查询 {hospital_name} 药品字典失败: {e}", exc_info=True)
        return {
            "data": [],
            "pagination": {
                "current_page": page,
                "page_size": page_size,
                "total_count": 0,
                "total_pages": 0,
                "has_next": False,
                "has_prev": False
            }
        }


# 方法3: 使用 Pydantic 的分页模型
from pydantic import BaseModel

class PaginationInfo(BaseModel):
    """分页信息模型"""
    current_page: int
    page_size: int
    total_count: int
    total_pages: int
    has_next: bool
    has_prev: bool

class PaginatedResponse(BaseModel):
    """分页响应模型"""
    data: List[Yp1]
    pagination: PaginationInfo
    success: bool = True
    message: str = "查询成功"

def get_drug_dict_with_pydantic_pagination(
    page: int = 1,
    page_size: int = 1000
) -> PaginatedResponse:
    """使用 Pydantic 模型的分页实现
    
    Args:
        page: 页码，从1开始
        page_size: 每页条数
        
    Returns:
        PaginatedResponse: 结构化的分页响应
    """
    hospital_config = get_hospital_config()
    hospital_name = hospital_config.get("name", "医院")
    
    try:
        logger.info(f"使用 Pydantic 分页查询 {hospital_name} 药品字典 (第 {page} 页，每页 {page_size} 条)")
        
        with get_db_session() as session:
            from sqlalchemy import func
            
            # 获取总数
            count_stmt = select(func.count(Yp1.idm))
            total = session.execute(count_stmt).scalar()
            
            # 分页查询
            offset = (page - 1) * page_size
            statement = select(Yp1).offset(offset).limit(page_size)
            results = session.execute(statement).scalars().all()
            
            # 计算分页信息
            total_pages = (total + page_size - 1) // page_size if total > 0 else 0
            has_next = page < total_pages
            has_prev = page > 1
            
            pagination_info = PaginationInfo(
                current_page=page,
                page_size=page_size,
                total_count=total,
                total_pages=total_pages,
                has_next=has_next,
                has_prev=has_prev
            )
            
            return PaginatedResponse(
                data=results,
                pagination=pagination_info
            )
            
    except Exception as e:
        logger.error(f"Pydantic 分页查询 {hospital_name} 药品字典失败: {e}", exc_info=True)
        return PaginatedResponse(
            data=[],
            pagination=PaginationInfo(
                current_page=page,
                page_size=page_size,
                total_count=0,
                total_pages=0,
                has_next=False,
                has_prev=False
            ),
            success=False,
            message=f"查询失败: {str(e)}"
        )


# 方法4: 使用装饰器模式
def paginate_query(func):
    """分页查询装饰器"""
    def wrapper(*args, **kwargs):
        page = kwargs.get('page', 1)
        page_size = kwargs.get('page_size', 1000)
        
        try:
            # 执行原始查询
            result = func(*args, **kwargs)
            
            # 添加分页信息
            if isinstance(result, list):
                total = len(result)
                start = (page - 1) * page_size
                end = start + page_size
                paginated_data = result[start:end]
                
                return {
                    "data": paginated_data,
                    "pagination": {
                        "current_page": page,
                        "page_size": page_size,
                        "total_count": total,
                        "total_pages": (total + page_size - 1) // page_size if total > 0 else 0,
                        "has_next": end < total,
                        "has_prev": page > 1
                    }
                }
            return result
            
        except Exception as e:
            logger.error(f"分页查询装饰器执行失败: {e}")
            return {
                "data": [],
                "pagination": {
                    "current_page": page,
                    "page_size": page_size,
                    "total_count": 0,
                    "total_pages": 0,
                    "has_next": False,
                    "has_prev": False
                },
                "error": str(e)
            }
    
    return wrapper

@paginate_query
def get_all_drugs():
    """获取所有药品数据（会被装饰器自动分页）"""
    with get_db_session() as session:
        statement = select(Yp1)
        results = session.execute(statement).scalars().all()
        return results


# 使用示例
if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    
    print("=== 方法1: fastapi-pagination 库 ===")
    try:
        result1 = get_drug_dict_with_fastapi_pagination(page=1, size=5)
        print(f"获取到 {len(result1.items)} 条数据")
        print(f"总数: {result1.total}, 总页数: {result1.pages}")
    except Exception as e:
        print(f"方法1失败: {e}")
    
    print("\n=== 方法2: SQLAlchemy 内置分页 ===")
    try:
        result2 = get_drug_dict_with_sqlalchemy_pagination(page=1, page_size=5)
        print(f"获取到 {len(result2['data'])} 条数据")
        print(f"分页信息: {result2['pagination']}")
    except Exception as e:
        print(f"方法2失败: {e}")
    
    print("\n=== 方法3: Pydantic 模型分页 ===")
    try:
        result3 = get_drug_dict_with_pydantic_pagination(page=1, page_size=5)
        print(f"获取到 {len(result3.data)} 条数据")
        print(f"分页信息: {result3.pagination}")
    except Exception as e:
        print(f"方法3失败: {e}")
    
    print("\n=== 方法4: 装饰器分页 ===")
    try:
        result4 = get_all_drugs(page=1, page_size=5)
        print(f"获取到 {len(result4['data'])} 条数据")
        print(f"分页信息: {result4['pagination']}")
    except Exception as e:
        print(f"方法4失败: {e}")
